#ifndef _STM8_FLASH_H_
#define _STM8_FLASH_H_

#include "mcu.h"


// 启用块写入，定义表示开启。【未实现，目前只能开启】
#define _FLASH_USE_BLOCK_WRITE   



//器件型号定义
#if (STM8_MCU_SERIES == MCU_STM8S003)
    #define STM8S003       	/*!< STM8S Value Line Low density devices */
#elif (STM8_MCU_SERIES == MCU_STM8S005)
    #define STM8S005       	/*!< STM8S Value Line Medium density devices */
#elif (STM8_MCU_SERIES == MCU_STM8S007)
    #define STM8S007       	/*!< STM8S Value Line High density devices */
#elif (STM8_MCU_SERIES == MCU_STM8S103)
    #define STM8S103       		/*!< STM8S Low density devices */
#elif (STM8_MCU_SERIES == MCU_STM8S105)
    #define STM8S105       			/*!< STM8S Medium density devices */
#elif (STM8_MCU_SERIES == MCU_STM8S207)
    #define STM8S207       	/*!< STM8S High density devices without CAN */
#elif (STM8_MCU_SERIES == MCU_STM8S208)
    #define STM8S208       	/*!< STM8S High density devices with CAN */
#elif (STM8_MCU_SERIES == MCU_STM8S903)
    #define STM8S903       	/*!< STM8S Low density devices */
#elif (STM8_MCU_SERIES == MCU_STM8AF626x)
    #define STM8AF626x     	/*!< STM8A Medium density devices */
#elif (STM8_MCU_SERIES == MCU_STM8AF62Ax)
    #define STM8AF62Ax     	/*!< STM8A High density devices without CAN */
#elif (STM8_MCU_SERIES == MCU_STM8AF52Ax)
    #define STM8AF52Ax     	/*!< STM8A High density devices with CAN */
#else
    #define STM8S207
    #warning "No MCU model is defined, the default STM8S207 model will be used."
#endif


#if !defined (STM8S208) && !defined (STM8S207) && !defined (STM8S105) && \
    !defined (STM8S103) && !defined (STM8S903) && !defined (STM8AF52Ax) && \
    !defined (STM8AF62Ax) && !defined (STM8AF626x) && !defined (STM8S007) && \
    !defined (STM8S003)&& !defined (STM8S005) 
 #error "Please select first the target STM8S/A device used in your application (in stm8s.h file)"
#endif
		
/* For FLASH routines, select whether pointer will be declared as near (2 bytes,
   to handle code smaller than 64KB) or far (3 bytes, to handle code larger 
   than 64K) */
#if defined (STM8S105) || defined (STM8S005) || defined (STM8S103) || defined (STM8S003) || \
    defined (STM8S903) || defined (STM8AF626x)
/*!< Used with memory Models for code smaller than 64K */
	#define PointerAttr __near
	#define faddr_t uint16_t
#else /* STM8S208 or STM8S207 or STM8AF62Ax or STM8AF52Ax */
/*!< Used with memory Models for code higher than 64K */
 #define PointerAttr __far
	#define faddr_t uint32_t
#endif /* STM8S105 or STM8S103 or STM8S003 or STM8S903 or STM8AF626x */      

//参数预定义
#define FLASH_CLEAR_BYTE    ((u8)0x00)
#define FLASH_SET_BYTE      ((u8)0xFF)
#define OPERATION_TIMEOUT   ((u8)0xFFFF)
			
#define FLASH_PROG_START_PHYSICAL_ADDRESS ((u32)0x008000) /*!< Program memory: start address */
#define FLASH_DATA_START_PHYSICAL_ADDRESS ((u32)0x004000) /*!< Data EEPROM memory: start address */

#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined (STM8AF52Ax) || defined (STM8AF62Ax)
 #define FLASH_PROG_END_PHYSICAL_ADDRESS   ((uint32_t)0x027FFF) /*!< Program memory: end address */
 #define FLASH_PROG_BLOCKS_NUMBER          ((uint16_t)1024)     /*!< Program memory: total number of blocks */
 #define FLASH_DATA_END_PHYSICAL_ADDRESS   ((uint32_t)0x0047FF) /*!< Data EEPROM memory: end address */
 #define FLASH_DATA_BLOCKS_NUMBER          ((uint16_t)16)       /*!< Data EEPROM memory: total number of blocks */
 #define FLASH_BLOCK_SIZE                  ((uint8_t)128)       /*!< Number of bytes in a block (common for Program and Data memories) */
#endif /* STM8S208, STM8S207, STM8S007, STM8AF52Ax, STM8AF62Ax */

#if defined(STM8S105) || defined(STM8S005) || defined(STM8AF626x)
 #define FLASH_PROG_END_PHYSICAL_ADDRESS   ((uint32_t)0xFFFF)   /*!< Program memory: end address */
 #define FLASH_PROG_BLOCKS_NUMBER          ((uint16_t)256)      /*!< Program memory: total number of blocks */
 #define FLASH_DATA_END_PHYSICAL_ADDRESS   ((uint32_t)0x0043FF) /*!< Data EEPROM memory: end address */
 #define FLASH_DATA_BLOCKS_NUMBER          ((uint16_t)8)        /*!< Data EEPROM memory: total number of blocks */
 #define FLASH_BLOCK_SIZE                  ((uint8_t)128)       /*!< Number of bytes in a block (common for Program and Data memories) */
#endif /* STM8S105 or STM8AF626x */

#if defined(STM8S103) || defined(STM8S003) || defined(STM8S001) || defined(STM8S903) || defined(STM8AF622x)
 #define FLASH_PROG_END_PHYSICAL_ADDRESS   ((uint32_t)0x9FFF)   /*!< Program memory: end address */
 #define FLASH_PROG_BLOCKS_NUMBER          ((uint16_t)128)      /*!< Program memory: total number of blocks */
 #define FLASH_DATA_END_PHYSICAL_ADDRESS   ((uint32_t)0x00427F) /*!< Data EEPROM memory: end address */
 #define FLASH_DATA_BLOCKS_NUMBER          ((uint16_t)10)       /*!< Data EEPROM memory: total number of blocks */
 #define FLASH_BLOCK_SIZE                  ((uint8_t)64)        /*!< Number of bytes in a block (common for Program and Data memories) */
#endif /* STM8S103 or STM8S003 or STM8S001 or STM8S903 or STM8AF622x*/

//自定义类型

// FLASH类型（区域）
typedef enum _flash_mem_type_t
{
    FLASH_MEMTYPE_PROG      = 0xFD, /*!< Program memory */
    FLASH_MEMTYPE_DATA      = 0xF7  /*!< Data EEPROM memory */
} flash_mem_type_t;

typedef enum _flash_status_t
{
#if defined (STM8S208) || defined(STM8S207) || defined(STM8S007) || defined(STM8S105) || \
    defined(STM8S005) || defined (STM8AF52Ax) || defined (STM8AF62Ax) || defined(STM8AF626x)		
    FLASH_STATUS_END_HIGH_VOLTAGE           = (uint8_t)0x40, /*!< End of high voltage */
#endif /* STM8S208, STM8S207, STM8S105, STM8AF62Ax, STM8AF52Ax, STM8AF626x */
    FLASH_STATUS_SUCCESSFUL_OPERATION       = (uint8_t)0x04, /*!< End of operation flag */
    FLASH_STATUS_TIMEOUT = (uint8_t)0x02, /*!< Time out error */
    FLASH_STATUS_WRITE_PROTECTION_ERROR     = (uint8_t)0x01 /*!< Write attempted to protected page */
} flash_status_t;



////////////////////////////////////////////////////////////////////////////////


// STM8，在指定const变量地址时，地址超过0X10000（FLASH从0X8000开始，所以是32KB空间）
// 就会出现链接错误，原因可能是超出了某个IAR自带库函数的范围，也可能是距离处理的代码
// 地址太远。暂时没有解决方案。所以这里定义FLASH_SIZE <= 32KB，这样定义指定地址的
// const变量，参照这个宏，使其地址不要超过32KB。
#define FLASH_SIZE  (32 * 1024l)

#define FLASH_PAGE_SIZE     FLASH_BLOCK_SIZE

/**
  * @brief  写入 OptionByte 区域。OptionByte 比较特殊，需要这个专用函数写入。
  * @param  Address  地址.
  * @param  Data  要写入的1字节数据.
  */
void Flash_WriteOptionByte(uint16_t Address, uint8_t Data);

/**
  * @brief  Returns the Boot memory size in bytes
  * @param  None
  * @retval Boot memory size in bytes
  */
uint32_t Flash_GetBootSize(void);

/**
  * @brief  写一整块数据
  * @param  Address : 块的首地址，必须是首地址
  * @param  Buffer : Pointer to buffer containing source data.
  * @retval None.
  */
void Flash_WriteBlock(faddr_t Address, const u8 *Buffer);

//安全的向FLASH的任意地址（包含EEPROM区域）写入任意数据
// addr: 地址
// dat : 数据
// len : 长度
void Flash_Write(faddr_t addr,const u8 * dat,u16 len);


#endif



